import json
import decimal

from django.db.models import Q, F
from django.shortcuts import render, get_object_or_404
from django.core.paginator import Paginator

from jewelry.models import Category, Product, SKU, ProductAttributeHistory
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
from django.template.loader import render_to_string
from django.views.decorators.csrf import csrf_exempt
from django.db.models import Prefetch
from django.core.cache import cache
from django.db import IntegrityError
from django.core.exceptions import ValidationError
from django.core.files.base import ContentFile
import hashlib
from rest_framework.decorators import api_view
from django.forms.models import model_to_dict
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
from .serializers import ProductSerializer


# 商品管理主视图
# def product_manage_view(request):
#     """
#     商品管理主视图（支持多对多分类关系）
#     返回HTML片段供base.html嵌入
#     """
#     # 1. 获取所有一级分类
#     main_categories = Category.objects.filter(parent__isnull=True).order_by('-id')
#
#     # 2. 获取当前选中的分类（默认为第一个）
#     selected_category_id = request.GET.get('category_id')
#     selected_category_name = ''
#     if not selected_category_id and main_categories:
#         selected_category_id = main_categories[0].id
#         selected_category_name = main_categories[0].name
#
#     # 3. 获取当前分类及其子分类下的商品（支持多对多关系）
#     products = Product.objects.all()
#     if selected_category_id:
#         # 获取当前分类及其所有后代分类
#         category = get_object_or_404(Category, id=selected_category_id)
#         child_categories = category.get_descendants(include_self=True)
#
#         # 修改为多对多查询
#         # 使用Q对象组合查询条件，确保包含所有相关分类的商品
#         products = products.filter(
#             Q(categories__in=child_categories) |
#             Q(categories__tree_id=category.tree_id,
#               categories__lft__gte=category.lft,
#               categories__rght__lte=category.rght)
#         ).distinct()  # 添加distinct避免重复结果
#
#     # 4. 搜索功能
#     search_query = request.GET.get('search')
#     if search_query:
#         # 扩展搜索范围：名称、描述、分类名称
#         products = products.filter(
#             Q(name__icontains=search_query) |
#             Q(description__icontains=search_query) |
#             Q(categories__name__icontains=search_query)
#         ).distinct()  # 避免重复
#
#     # 5. 分页处理
#     paginator = Paginator(products, 10)  # 每页10条
#     page_number = request.GET.get('page', 1)
#     page_obj = paginator.get_page(page_number)
#
#     # 6. 准备上下文数据
#     from django.core import serializers
#     context = {
#         'main_categories': main_categories,
#         'selected_category_id': int(selected_category_id) if selected_category_id else None,
#         'selected_category_name': selected_category_name,
#         'products': serializers.serialize('json', page_obj.object_list),
#         'page_obj': page_obj,
#         'search_query': search_query or ''
#     }
#
#     html = render_to_string('ecom/product/product_manage.html', context, request=request)
#
#     # 7. 返回JSON给base主页
#     return JsonResponse({
#         'html': html,
#         'data': {'tabId': 'product_manage'},
#         'js_files': [{
#             'type': 'esm',
#             'path': 'static/ecom/product/js/product_manage.js',
#             'inlineCode': None
#         }],
#     })


# class CustomPagination(PageNumberPagination):
#     page_size = 10
#     page_size_query_param = 'page_size'
#     max_page_size = 100
class ProductPagination(PageNumberPagination):
    page_size = 10
    page_query_param = 'page'

    def get_paginated_data(self, data):
        return {
            'current_page': self.page.number,
            'total_pages': self.page.paginator.num_pages,
            'total_items': self.page.paginator.count,
            'results': data
        }


@api_view(['GET'])
def product_manage_view(request):
    # 1. 获取所有一级分类
    main_categories = Category.objects.filter(parent__isnull=True).order_by('-id')

    # 2. 获取当前选中的分类
    selected_category_id = request.GET.get('category_id')
    selected_category_name = ''
    if not selected_category_id and main_categories:
        selected_category_id = main_categories[0].id
        selected_category_name = main_categories[0].name

    # 3. 获取商品查询集（包含所有字段）
    # products = Product.objects.all().select_related('category').prefetch_related('categories')
    products = Product.objects.all().prefetch_related('categories')
    # products = Product.objects.all().prefetch_related(
    #     Prefetch('categories', queryset=Category.objects.only('id', 'name')))
    # 分类筛选
    if selected_category_id:
        category = get_object_or_404(Category, id=selected_category_id)
        child_categories = category.get_descendants(include_self=True)
        products = products.filter(
            Q(categories__in=child_categories) |
            Q(categories__tree_id=category.tree_id,
              categories__lft__gte=category.lft,
              categories__rght__lte=category.rght)
        ).distinct()

    # 4. 搜索功能
    search_query = request.GET.get('search')
    if search_query:
        products = products.filter(
            Q(name__icontains=search_query) |
            Q(description__icontains=search_query) |
            Q(categories__name__icontains=search_query)
        ).distinct()

    # 分页+序列化
    # paginator = ProductPagination()
    # paginated_products = paginator.paginate_queryset(products, request)
    # serializer = ProductSerializer(paginated_products, many=True, context={'request': request})
    # 分页（兼容模板）
    paginator = Paginator(products, 10)
    page_number = request.GET.get('page', 1)
    page_obj = paginator.get_page(page_number)
    # 序列化
    serializer = ProductSerializer(page_obj.object_list, many=True, context={'request': request})

    # 7. 渲染HTML
    html_context = {
        'main_categories': main_categories,
        'selected_category_id': int(selected_category_id) if selected_category_id else None,
        'selected_category_name': selected_category_name,
        'products': serializer.data,
        "pagination": {
            "current_page": page_obj.number,
            "total_pages": paginator.num_pages,
            "total_items": paginator.count,
            "has_prev": page_obj.has_previous(),
            "has_next": page_obj.has_next(),
        }
    }

    html = render_to_string('ecom/product/product_manage.html', html_context, request=request)  # 数据藏于模版中

    # 8. 返回响应
    return Response({
        'html': html,
        'products': serializer.data,
        "pagination": {
            "current_page": page_obj.number,
            "total_pages": paginator.num_pages,
            "total_items": paginator.count,
            "has_prev": page_obj.has_previous(),
            "has_next": page_obj.has_next(),
        },
        'data': {'tabId': 'product_manage'},
        'js_files': [{
            'type': 'esm',
            'path': 'static/ecom/product/js/product_manage.js',
            'inlineCode': None
        }]
    })


# 创建或修改分类
@require_http_methods(["POST"])
def create_or_update_category(request):
    # 获取请求参数
    try:
        json_str = request.body.decode('utf-8')
        data = json.loads(json_str)
    except json.JSONDecodeError:
        return JsonResponse({'error': '无效的JSON格式'}, status=400)

    category_id = data.get('id')
    parent_id = data.get('parent_id')
    name = data.get('name', '').strip()  # 清理空白字符

    # 验证必要参数
    if not name:
        return JsonResponse({'error': '分类名称不能为空'}, status=400)

    # 处理父分类
    parent = None
    if parent_id:
        try:
            parent = Category.objects.get(id=parent_id)
        except Category.DoesNotExist:
            return JsonResponse({'error': '父分类不存在'}, status=404)

    # ===== 核心：支持创建和更新两种模式 =====
    try:
        if category_id:  # 修改现有分类
            category = get_object_or_404(Category, id=category_id)

            # 防止循环引用（父分类不能是自身或后代）
            if parent and (parent.id == category.id or parent.is_descendant_of(category)):
                return JsonResponse({'error': '无效的父分类关系：不能将分类设置为自身或后代的子类'}, status=400)

            # 唯一性验证（根分类或子分类）
            validation_error = validate_category_uniqueness(name, parent, category)
            if validation_error:
                return JsonResponse({'error': validation_error}, status=400)

            # 更新分类
            category.name = name
            category.parent = parent
            category.save()  # 触发层级更新
            action = 'updated'

        else:  # 创建新分类
            # 唯一性验证（根分类或子分类）
            validation_error = validate_category_uniqueness(name, parent)
            if validation_error:
                return JsonResponse({'error': validation_error}, status=400)

            # 创建分类
            category = Category.objects.create(name=name, parent=parent)
            action = 'created'

    except IntegrityError as e:
        # 捕获数据库级别的唯一性约束错误（并发情况下的最后防线）
        return JsonResponse({'error': '分类名称冲突，请重试'}, status=400)

    except ValidationError as e:
        # 捕获模型级别的验证错误
        return JsonResponse({'error': e.message}, status=400)

    # 返回统一响应格式
    return JsonResponse({
        'action': action,
        'id': category.id,
        'name': category.name,
        'level': category.level,
        'parent_id': parent.id if parent else None
    })


# 唯一性验证（根分类或子分类）
def validate_category_uniqueness(name, parent, existing_category=None):
    """
    验证分类名称的唯一性（根分类全局唯一，子分类在父分类下唯一）

    参数:
    - name: 分类名称
    - parent: 父分类对象（None表示根分类）
    - existing_category: 更新操作时排除的当前分类对象

    返回:
    - 错误消息字符串（验证通过返回None）
    """
    # 构建查询集：查找同名的分类
    queryset = Category.objects.filter(name=name)

    # 排除当前分类（更新操作时）
    if existing_category:
        queryset = queryset.exclude(id=existing_category.id)

    # 根分类验证：全局唯一
    if parent is None:
        # 查找所有根分类中同名的（parent=None）
        if queryset.filter(parent__isnull=True).exists():
            return '根分类名称必须全局唯一'

    # 子分类验证：在父分类下唯一
    else:
        # 查找同一父分类下同名的子分类
        if queryset.filter(parent=parent).exists():
            return '同一父分类下的子分类名称必须唯一'

    return None


# 删除分类
@require_http_methods(["DELETE"])  # 确保只响应DELETE请求
def delete_category(request, categoryId):
    try:
        # 1. 获取要删除的分类
        category = Category.objects.get(id=categoryId)
        parent_id = category.parent_id  # 直接获取父类ID字段的值

        # 2. 检查是否有子分类（根据资料中的最佳实践）[[1]][[9]]
        if category.children.exists():
            return JsonResponse({
                "status": "error",
                "message": "无法删除含有子分类的类别"
            }, status=400)

        # 3. 执行删除操作
        category.delete()  # 物理删除
        # 或使用逻辑删除：category.is_active = False; category.save()

        # 4. 返回成功响应
        return JsonResponse({
            "status": "success",
            "message": "分类删除成功",
            "deleted_id": categoryId,
            "parent_id": parent_id
        })

    except Category.DoesNotExist:
        return JsonResponse({
            "status": "error",
            "message": "分类不存在"
        }, status=404)

    except Exception as e:
        return JsonResponse({
            "status": "error",
            "message": f"服务器错误: {str(e)}"
        }, status=500)


# 点击分类名获取商品
def get_products_by_category(request):
    """获取指定分类及其子分类下的商品（支持多对多关系）"""
    # 1. 参数验证与缓存检查
    category_id = request.GET.get('category_id')
    if not category_id:
        return JsonResponse({'error': '缺少分类ID参数'}, status=400)

    # 检查缓存
    cache_key = f'products_by_category_{category_id}'
    if cached := cache.get(cache_key):
        return JsonResponse({'products': cached})

    try:
        # 2. 获取分类树
        category = Category.objects.get(id=category_id)
        descendant_categories = category.get_descendants(include_self=True)

        # 3. 多对多查询优化
        products = Product.objects.filter(
            categories__in=descendant_categories
        ).prefetch_related(
            Prefetch('categories',
                     queryset=Category.objects.only('id', 'name'))
        ).distinct()

        # 4. 数据序列化
        product_data = [{
            'id': p.id,
            'thumbnail_url': p.thumbnail.url if p.thumbnail else None,
            'name': p.name,
            'stock': p.stock,
            'price': float(p.price),  # Decimal转float
            'is_active': p.is_active,
            'categories': [c.name for c in p.categories.all()]  # 添加分类信息
        } for p in products]

        # 5. 设置缓存
        cache.set(cache_key, product_data, timeout=60 * 15)  # 缓存15分钟

        return JsonResponse({'products': product_data})

    except Category.DoesNotExist:
        return JsonResponse({'error': '分类不存在'}, status=404)
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)


# 添加子分类
@csrf_exempt
def add_subcategory(request):
    if request.method == 'POST':
        name = request.POST.get('name')
        parent_id = request.POST.get('parent_id')

        if not name:
            return JsonResponse({'success': False, 'error': '分类名称不能为空'})

        try:
            parent = Category.objects.get(id=parent_id)
            # 2. 调用唯一性验证函数

            uniqueness_error = validate_category_uniqueness(name, parent)
            if uniqueness_error:
                return JsonResponse({'success': False, 'error': uniqueness_error})

            # 创建子分类
            new_category = Category.objects.create(
                name=name,
                parent=parent,
                level=parent.level + 1  # 层级递增
            )
            # return JsonResponse({'success': True})
            return JsonResponse({
                'success': True,
                'new_category': {
                    'parent_id': parent_id,
                    'id': new_category.id,
                    'name': new_category.name,
                    'level': new_category.level
                }
            })
        except Category.DoesNotExist:
            return JsonResponse({'success': False, 'error': '父分类不存在'})
        except Exception as e:
            return JsonResponse({'success': False, 'error': str(e)})

    return JsonResponse({'success': False, 'error': '无效请求'})


# 新增商品
@csrf_exempt
@require_http_methods(["POST"])
def create_product(request):
    try:
        # 获取表单数据
        name = request.POST.get('name')
        description = request.POST.get('description')
        categories = request.POST.getlist('categories')

        # 创建商品
        product = Product.objects.create(
            name=name,
            description=description,
            is_active=True
        )

        # 添加分类
        if categories:
            product.categories.set(categories)

        # 处理主图
        main_images = request.FILES.getlist('main_images')
        for img in main_images:
            # 这里需要根据你的实际模型保存图片
            # 例如: ProductImage.objects.create(product=product, image=img)
            pass

        # 处理视频
        video = request.FILES.get('video')
        if video:
            product.video_url.save(video.name, ContentFile(video.read()))

        # 处理SKU
        skus_data = json.loads(request.POST.get('skus', '[]'))
        min_price = None
        total_stock = 0

        for sku_data in skus_data:
            # 生成属性哈希
            attributes = sku_data['attributes']
            attributes_hash = hashlib.sha256(attributes.encode()).hexdigest()

            # 创建SKU
            sku = SKU.objects.create(
                product=product,
                attributes_json=attributes,
                attributes_hash=attributes_hash,
                price=sku_data['price'],
                original_price=sku_data.get('original_price', sku_data['price']),
                stock=sku_data['stock'],
                is_active=True
            )

            # 处理SKU图片
            if sku_data.get('image'):
                sku.image.save(sku_data['image'].name, ContentFile(sku_data['image'].read()))

            # 计算最低价和总库存
            price = float(sku_data['price'])
            if min_price is None or price < min_price:
                min_price = price
            total_stock += int(sku_data['stock'])

        # 更新商品总库存和最低价
        product.stock = total_stock
        product.price = min_price if min_price is not None else 0
        product.save()

        return JsonResponse({
            'success': True,
            'product_id': product.id,
            'message': '商品创建成功'
        })

    except Exception as e:
        return JsonResponse({
            'success': False,
            'message': str(e)
        }, status=400)


# 获取分类层级更新(分类下拉选择框使用)
def product_category(request):
    # 获取所有根节点分类
    root_categories = Category.objects.filter(parent=None).prefetch_related('children')

    # 递归构建树形结构（保持不变）
    def build_tree(node):
        node_dict = model_to_dict(node, fields=['id', 'name'])
        children = node.get_children()
        if children:
            node_dict['children'] = [build_tree(child) for child in children]
        return node_dict

    categories_tree = [build_tree(root) for root in root_categories]

    # 直接返回 JsonResponse，前端可调用 initCategoryTree(data)
    return JsonResponse(categories_tree, safe=False)  # safe=False 允许返回列表,不加默认是字典


# 更新商品
@require_http_methods(["POST"])
def update_product(request, pk):
    """更新商品API"""
    try:
        # 获取商品对象，如果不存在则返回404
        product = get_object_or_404(Product, id=pk)

        # 更新商品的基本字段
        product.name = request.POST.get('name', product.name)
        # 库存转换为整数
        stock = request.POST.get('stock')
        if stock is not None:
            product.stock = int(stock)
        # 价格转换为Decimal
        price = request.POST.get('price')
        if price is not None:
            product.price = decimal.Decimal(price)
        # 更新商品状态（上架/下架）
        is_active = request.POST.get('is_active')
        if is_active is not None:
            product.is_active = (is_active.lower() == 'true')

        # 处理缩略图上传
        if 'thumbnail' in request.FILES:
            product.thumbnail = request.FILES['thumbnail']

        # 保存更新
        product.save()

        # 构造返回数据
        data = {
            'id': product.id,
            'name': product.name,
            'stock': product.stock,
            'price': str(product.price),  # 转换为字符串避免序列化问题
            'is_active': product.is_active,
            'thumbnail_url': product.thumbnail.url if product.thumbnail else ''
        }
        return JsonResponse(data)

    except (ValueError, decimal.InvalidOperation) as e:
        # 处理数值转换错误
        return JsonResponse({'error': f'无效的数值: {str(e)}'}, status=400)
    except Exception as e:
        # 处理其他异常
        return JsonResponse({'error': f'更新失败: {str(e)}'}, status=500)


# 新的属性名+属性值
@api_view(['GET'])
def product_edit_view(request, pk=None):
    product = Product.objects.get(pk=pk) if pk else None

    # 新增：序列化details数据
    details_data = []
    if product and product.details:
        details_data = [
            {key: value} for item in product.details
            for key, value in item.items()
        ]

    return render(request, 'ecom/product/product_form.html', {
        'product': product,
        'details_json': JsonResponse(details_data, safe=False).content.decode()  # 预序列化
    })
    # return render(request, 'ecom/product/product_form.html', {
    #     'product': product,
    #     'details_data': details_data  # 直接传递Python对象
    # })


# views.py 优化建议
@api_view(['GET'])
def attribute_history_api(request):
    """API获取所有历史属性键（按使用频率排序）"""
    history = ProductAttributeHistory.objects.order_by('-usage_count', '-last_used')
    # 添加最近使用过的5个值作为建议
    data = []
    for item in history:
        # 获取最近5个值（根据实际需求调整）
        recent_values = Product.objects.exclude(
            details__contains=[{item.key: ''}]
        ).values_list(f'details__{item.key}', flat=True).distinct()[:5]

        data.append({
            'key': item.key,
            'last_value': item.last_value,
            'usage_count': item.usage_count,
            'last_used': item.last_used,
            # 'recent_values': list(recent_values)
        })

    return JsonResponse(data, safe=False)
